package cn.lblbc.webbrowser.utils

import android.content.Context
import android.os.Environment
import android.webkit.CookieManager
import android.webkit.URLUtil
import android.widget.Toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.net.HttpURLConnection
import java.net.URL
import java.util.concurrent.ConcurrentHashMap

/**
 * 自定义下载器，用于在Android 13+上替代DownloadManager
 */
class CustomDownloader(private val context: Context) {
    // 完成的下载管理器
    private val completedDownloadManager = CompletedDownloadManager(context)
    // 存储正在进行的下载任务
    private val activeDownloads = ConcurrentHashMap<Long, DownloadTask>()
    // 下一个下载ID
    private var nextDownloadId = 1000L
    
    /**
     * 开始下载文件
     */
    fun downloadFile(url: String, userAgent: String, contentDisposition: String, mimeType: String) {
        try {
            println("【自定义下载器】开始处理下载请求")
            println("【自定义下载器】URL: $url")
            println("【自定义下载器】User-Agent: ${userAgent.take(50)}...")
            println("【自定义下载器】Content-Disposition: $contentDisposition")
            println("【自定义下载器】MIME类型: $mimeType")
            println("【自定义下载器】Android版本: ${android.os.Build.VERSION.SDK_INT}")
            println("【自定义下载器】设备型号: ${android.os.Build.MODEL}")
            
            // 首先检查是否是百度APK下载链接
            if (isBaiduApkDownloadUrl(url)) {
                println("【自定义下载器】检测到百度APK下载链接")
                // 如果是百度APK下载链接，直接使用APK扩展名
                val timestamp = System.currentTimeMillis()
                val fileName = "baidu_app_$timestamp.apk"
                downloadWithFileName(url, userAgent, fileName, mimeType)
                return
            }
            
            // 获取文件名
            var fileName = URLUtil.guessFileName(url, contentDisposition, mimeType)
            println("【自定义下载器】猜测的文件名: $fileName")
            
            // 如果文件名为空，使用时间戳作为文件名
            if (fileName.isNullOrEmpty()) {
                fileName = "download_${System.currentTimeMillis()}"
                
                // 尝试从URL中提取文件扩展名
                val urlExtension = extractExtensionFromUrl(url)
                if (urlExtension.isNotEmpty()) {
                    fileName += ".$urlExtension"
                }
                // 如果URL中没有扩展名，则根据MIME类型添加适当的扩展名
                else if (!mimeType.isNullOrEmpty()) {
                    when {
                        mimeType.contains("image/") -> fileName += ".jpg"
                        mimeType.contains("video/") -> fileName += ".mp4"
                        mimeType.contains("audio/") -> fileName += ".mp3"
                        mimeType.contains("application/pdf") -> fileName += ".pdf"
                        mimeType.contains("application/zip") -> fileName += ".zip"
                        mimeType.contains("application/vnd.android.package-archive") -> fileName += ".apk"
                        mimeType.contains("text/") -> fileName += ".txt"
                        else -> fileName += ".bin"
                    }
                } else {
                    fileName += ".bin"
                }
                println("【自定义下载器】生成的文件名: $fileName")
            } else if (!fileName.contains(".")) {
                // 文件名不包含扩展名
                if (isBaiduApkDownloadUrl(url)) {
                    fileName += ".apk"
                } else {
                    // 尝试从URL中提取文件扩展名
                    val urlExtension = extractExtensionFromUrl(url)
                    if (urlExtension.isNotEmpty()) {
                        fileName += ".$urlExtension"
                    } else if (!mimeType.isNullOrEmpty() && mimeType.contains("application/vnd.android.package-archive")) {
                        fileName += ".apk"
                    }
                }
                println("【自定义下载器】添加扩展名后的文件名: $fileName")
            } else if (fileName.endsWith(".bin") && isBaiduApkDownloadUrl(url)) {
                // 如果文件名以.bin结尾，但URL是百度APK下载链接，则替换扩展名为.apk
                fileName = fileName.substring(0, fileName.length - 4) + ".apk"
                println("【自定义下载器】修正为APK文件名: $fileName")
            }
            
            downloadWithFileName(url, userAgent, fileName, mimeType)
        } catch (e: Exception) {
            println("【自定义下载器】下载请求处理失败: ${e.message}")
            e.printStackTrace()
            try {
                Toast.makeText(context, "下载失败: ${e.message}", Toast.LENGTH_SHORT).show()
            } catch (e: Exception) {
                // 忽略Toast显示错误
                e.printStackTrace()
            }
        }
    }
    
    /**
     * 使用指定的文件名下载文件
     */
    private fun downloadWithFileName(url: String, userAgent: String, fileName: String, mimeType: String = "application/octet-stream") {
        try {
            println("【自定义下载器】准备下载文件")
            println("【自定义下载器】URL: $url")
            println("【自定义下载器】文件名: $fileName")
            println("【自定义下载器】MIME类型: $mimeType")
            
            // 确定下载目录
            val downloadDir = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
                // Android 13+ 尝试使用应用专用下载目录
                context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
            } else {
                // Android 12及以下使用公共下载目录
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
            }
            
            println("【自定义下载器】下载目录: ${downloadDir?.absolutePath}")
            
            if (downloadDir == null) {
                println("【自定义下载器】下载目录为空，无法下载")
                Toast.makeText(context, "无法访问下载目录", Toast.LENGTH_SHORT).show()
                return
            }
            
            // 确保下载目录存在
            if (!downloadDir.exists()) {
                val created = downloadDir.mkdirs()
                println("【自定义下载器】创建下载目录: $created")
            }
            
            // 检查下载目录是否可写
            val canWrite = downloadDir.canWrite()
            println("【自定义下载器】下载目录是否可写: $canWrite")
            
            if (!canWrite) {
                println("【自定义下载器】下载目录不可写，无法下载")
                Toast.makeText(context, "下载目录不可写", Toast.LENGTH_SHORT).show()
                return
            }
            
            // 创建目标文件
            val file = File(downloadDir, fileName)
            println("【自定义下载器】目标文件路径: ${file.absolutePath}")
            
            // 生成下载ID
            val downloadId = nextDownloadId++
            println("【自定义下载器】下载ID: $downloadId")
            
            // 创建下载任务
            val downloadTask = DownloadTask(
                id = downloadId,
                url = url,
                userAgent = userAgent,
                fileName = fileName,
                mimeType = mimeType,
                file = file,
                totalSize = -1L,
                downloadedSize = 0L
            )
            
            // 添加到活动下载列表
            activeDownloads[downloadId] = downloadTask
            
            // 显示下载开始的提示
            Toast.makeText(context, "开始下载: $fileName", Toast.LENGTH_SHORT).show()
            
            // 在协程中执行下载
            CoroutineScope(Dispatchers.IO).launch {
                try {
                    println("【自定义下载器】开始下载任务: $downloadId")
                    
                    // 创建URL连接
                    val connection = URL(url).openConnection() as HttpURLConnection
                    connection.requestMethod = "GET"
                    connection.connectTimeout = 15000
                    connection.readTimeout = 15000
                    
                    // 设置User-Agent
                    if (userAgent.isNotEmpty()) {
                        connection.setRequestProperty("User-Agent", userAgent)
                    }
                    
                    // 设置Cookie
                    val cookies = CookieManager.getInstance().getCookie(url)
                    if (!cookies.isNullOrEmpty()) {
                        connection.setRequestProperty("Cookie", cookies)
                    }
                    
                    // 添加其他请求头
                    connection.setRequestProperty("Accept", "*/*")
                    connection.setRequestProperty("Accept-Encoding", "identity")
                    connection.setRequestProperty("Connection", "keep-alive")
                    
                    // 连接
                    connection.connect()
                    
                    // 检查响应码
                    val responseCode = connection.responseCode
                    println("【自定义下载器】HTTP响应码: $responseCode")
                    
                    if (responseCode != HttpURLConnection.HTTP_OK) {
                        println("【自定义下载器】HTTP请求失败: $responseCode")
                        withContext(Dispatchers.Main) {
                            Toast.makeText(context, "下载失败: HTTP $responseCode", Toast.LENGTH_SHORT).show()
                        }
                        activeDownloads.remove(downloadId)
                        return@launch
                    }
                    
                    // 获取文件大小
                    val contentLength = connection.contentLength
                    println("【自定义下载器】文件大小: $contentLength 字节")
                    
                    // 更新下载任务信息
                    downloadTask.totalSize = contentLength.toLong()
                    
                    // 创建输入流和输出流
                    val inputStream = connection.inputStream
                    val outputStream = FileOutputStream(file)
                    
                    // 下载文件
                    val buffer = ByteArray(4096)
                    var bytesRead: Int
                    var totalBytesRead = 0L
                    var lastProgressUpdate = 0L
                    
                    while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                        outputStream.write(buffer, 0, bytesRead)
                        totalBytesRead += bytesRead
                        downloadTask.downloadedSize = totalBytesRead
                        
                        // 每100ms更新一次进度
                        val now = System.currentTimeMillis()
                        if (now - lastProgressUpdate > 100) {
                            lastProgressUpdate = now
                            val progress = if (contentLength > 0) {
                                (totalBytesRead * 100 / contentLength).toInt()
                            } else {
                                -1
                            }
                            println("【自定义下载器】下载进度: $progress% ($totalBytesRead/$contentLength)")
                        }
                    }
                    
                    // 关闭流
                    outputStream.flush()
                    outputStream.close()
                    inputStream.close()
                    
                    println("【自定义下载器】下载完成: ${file.absolutePath}")
                    
                    // 下载完成，从活动下载列表中移除
                    activeDownloads.remove(downloadId)
                    
                    // 保存完成的下载项
                    completedDownloadManager.saveCompletedDownload(
                        downloadId = downloadId,
                        fileName = fileName,
                        filePath = file.absolutePath,
                        fileSize = totalBytesRead,
                        mimeType = mimeType
                    )
                    
                    // 显示下载完成的提示
                    withContext(Dispatchers.Main) {
                        Toast.makeText(context, "下载完成: $fileName", Toast.LENGTH_SHORT).show()
                    }
                } catch (e: Exception) {
                    println("【自定义下载器】下载过程中出错: ${e.message}")
                    e.printStackTrace()
                    
                    // 从活动下载列表中移除
                    activeDownloads.remove(downloadId)
                    
                    // 显示错误提示
                    withContext(Dispatchers.Main) {
                        Toast.makeText(context, "下载失败: ${e.message}", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        } catch (e: Exception) {
            println("【自定义下载器】准备下载过程中出错: ${e.message}")
            e.printStackTrace()
            Toast.makeText(context, "下载失败: ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
    
    /**
     * 获取所有活动的下载任务
     */
    fun getActiveDownloads(): List<DownloadTask> {
        return activeDownloads.values.toList()
    }
    
    /**
     * 检查URL是否是百度APK下载链接
     */
    private fun isBaiduApkDownloadUrl(url: String): Boolean {
        val lowerUrl = url.lowercase()
        return lowerUrl.contains("ms-gdown.baidu.com") || 
               lowerUrl.contains("gdown.baidu.com") || 
               lowerUrl.contains("appcenter/pkg") ||
               lowerUrl.contains("packagemapid") ||
               lowerUrl.contains("md5hash") ||
               (lowerUrl.contains("baidu.com") && lowerUrl.contains("download"))
    }
    
    /**
     * 从URL中提取文件扩展名
     */
    private fun extractExtensionFromUrl(url: String): String {
        println("【自定义下载器】从URL提取扩展名: $url")
        
        // 检查URL中是否包含查询参数
        val urlWithoutQuery = url.split("?")[0]
        println("【自定义下载器】去除查询参数后的URL: $urlWithoutQuery")
        
        // 检查URL路径中是否包含文件扩展名
        val lastDotIndex = urlWithoutQuery.lastIndexOf(".")
        if (lastDotIndex != -1 && lastDotIndex < urlWithoutQuery.length - 1) {
            val extension = urlWithoutQuery.substring(lastDotIndex + 1)
            println("【自定义下载器】找到可能的扩展名: $extension")
            
            // 只返回合法的文件扩展名（不超过10个字符且只包含字母和数字）
            if (extension.length <= 10 && extension.matches(Regex("[a-zA-Z0-9]+"))) {
                println("【自定义下载器】确认有效的扩展名: $extension")
                return extension
            } else {
                println("【自定义下载器】扩展名无效: $extension")
            }
        } else {
            println("【自定义下载器】URL中没有找到扩展名")
        }
        
        // 检查特定的下载URL模式
        if (url.contains("ms-gdown.baidu.com") || url.contains("gdown.baidu.com")) {
            return "apk"
        }
        
        // 检查URL中的文件类型提示
        val lowerUrl = url.lowercase()
        return when {
            lowerUrl.contains("filetype=apk") || lowerUrl.contains("type=apk") -> "apk"
            lowerUrl.contains("filetype=pdf") || lowerUrl.contains("type=pdf") -> "pdf"
            lowerUrl.contains("filetype=zip") || lowerUrl.contains("type=zip") -> "zip"
            lowerUrl.contains("filetype=doc") || lowerUrl.contains("type=doc") -> "doc"
            lowerUrl.contains("filetype=docx") || lowerUrl.contains("type=docx") -> "docx"
            lowerUrl.contains("filetype=xls") || lowerUrl.contains("type=xls") -> "xls"
            lowerUrl.contains("filetype=xlsx") || lowerUrl.contains("type=xlsx") -> "xlsx"
            lowerUrl.contains("filetype=ppt") || lowerUrl.contains("type=ppt") -> "ppt"
            lowerUrl.contains("filetype=pptx") || lowerUrl.contains("type=pptx") -> "pptx"
            else -> ""
        }
    }
    
    /**
     * 下载任务数据类
     */
    data class DownloadTask(
        val id: Long,
        val url: String,
        val userAgent: String,
        val fileName: String,
        val mimeType: String,
        val file: File,
        var totalSize: Long,
        var downloadedSize: Long
    )
}